package com.ityu.common.config;

import io.github.classgraph.ModuleRef;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import springfox.documentation.builders.ModelSpecificationBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.RequestParameterBuilder;
import springfox.documentation.schema.ModelSpecification;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spi.service.contexts.SecurityContextBuilder;
import springfox.documentation.spring.web.plugins.Docket;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 文档配置
 *
 * @author lihe
 */
public abstract class BaseSwaggerConfig {


    private final static String TOKEN = "token";
    private final static String DEVICE_NO = "deviceNo";
    private final static String USER_ID = "userId";

    private final static String PASS_AS = "header";


    /**
     * 子类用于自定义接口参数
     *
     * @return api 配置
     */
    protected abstract ApiInfo apiInfo();


    @Bean
    public Docket createRestApi(Environment env) {
        RequestParameterBuilder ticketPar = new RequestParameterBuilder().name("Authorization").description("用户信息").required(false);
        List<RequestParameter> pars = new ArrayList<>();
        ticketPar.in(ParameterType.HEADER).contentModel(new ModelSpecificationBuilder().name("string").build());
        RequestParameter parameter = ticketPar.build();

        //header中的ticket参数非必填，传空也可以

        pars.add(parameter);    //根据每个方法名也知道当前方法在设置什么参数

        List<SecurityContext> data = new ArrayList();

        data.add(securityContext());

        //是否是
        boolean activeProfiles = env.acceptsProfiles(Profiles.of("dev"));


        return new Docket(DocumentationType.OAS_30)
                .securitySchemes(security())
                .securityContexts(data)
                .enable(activeProfiles)
                .apiInfo(apiInfo())
                .globalRequestParameters(pars)
                .select()
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build();
    }


    private Stream<String> getKeyStream() {
        return Stream.of(TOKEN, DEVICE_NO, USER_ID);
    }


    private List<SecurityScheme> security() {
        return this.getKeyStream()
                .map(x -> new ApiKey(x, x, PASS_AS))
                .collect(Collectors.toList());
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.any())
                //.operationSelector(new SecurityContextBuilder().operationSelector(new OperationContext().pathMatches()))
                .build();
    }

    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope
                = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return this.getKeyStream()
                .map(x -> new SecurityReference(x, authorizationScopes))
                .collect(Collectors.toList());
    }
}
